/**
 * 
 */
package gates;

import gates.internals.ITransistor;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @author denis
 *
 */
public abstract class Gate implements IGate {
	protected static String filename;
	protected GateInput input_1, input_2;
	protected GateOutput output;
	protected Battery bat;
	protected Ground gnd;
	protected int defect;
	protected List<ITransistor> components = new ArrayList<ITransistor>();
	
	public Gate() {}
	
	public Gate(GateInput in_1, GateInput in_2, int defect) {
		input_1 = in_1;
		input_2 = in_2;
		output = new GateOutput();
		bat = new Battery();
		gnd = new Ground();
		this.defect = defect;
		generateCircuit();
		setOldValues();
		sendSignals();
		saveValuesToFile();
	}
	
	protected void setOldValues() {
		if (!new File(filename).exists()) {
			return;
		}
		Properties properties = new Properties();
		try {
			properties.load(new FileInputStream(filename));
			for (ITransistor transistor : components) {
				transistor.setOldValues(
						getBooleanValueFromString(properties.getProperty(transistor
								.getName() + ".b")),
						getBooleanValueFromString(properties.getProperty(transistor
								.getName() + ".e")),
						getBooleanValueFromString(properties.getProperty(transistor
								.getName() + ".c")));
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	private Boolean getBooleanValueFromString(String stringValue) {
		return "null".equalsIgnoreCase(stringValue) ? null : Boolean
				.valueOf(stringValue);
	}

	protected void saveValuesToFile() {
		Properties properties = new Properties();
		for (ITransistor transistor : components) {
			properties = transistor.getStateAsProperties(properties);
		}
		try {
			properties.store(new FileOutputStream(filename), null);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	private void sendSignals() {
		bat.sendSignal();
		gnd.sendSignal();
		input_1.sendSignal();
		input_2.sendSignal();
	}
	
	protected abstract void generateCircuit();
	
	public boolean getOutput() {
		return output.getValue();
	}
	
	public int getDefect() {
		return defect;
	}
}
